import logging

import pytz
from aiogram import Bot
from arq import cron

import src.database.services as services
from src.bot.services.locale import configure_localizator
from src.bot.worker.jobs import (
    enque_calendar_tasks,
    notify_expired_subscription,
    notify_expiring_subscription,
    notify_user,
    notify_users,
)
from src.config import load_config
from src.core.constants import LOCALES_FOLDER
from src.core.logger import configure_logging
from src.database.main import build_sa_engine, build_sa_session_factory
from src.database.uow.uow import build_uow

config = load_config()

logger = logging.getLogger(__name__)


def generate_run_time(x: int, start: int, end: int) -> set:
    """Generate set with x period between start and end interval"""
    return {*list(range(start, end, x))}


async def startup(ctx):
    configure_logging()
    logger.info("Starting worker")
    engine = build_sa_engine(config.db)
    ctx["engine"] = engine
    ctx["sessionmaker"] = build_sa_session_factory(engine)
    ctx["config"] = config
    ctx["bot"] = Bot(token=config.tg_bot.token, parse_mode="HTML")
    ctx["localizator"] = configure_localizator(LOCALES_FOLDER)


async def on_job_start(ctx):
    """Прокидываем зависимости в задачу"""

    session = ctx["sessionmaker"]()
    uow = build_uow(session)
    ctx["session"] = session
    ctx["uow"] = uow
    ctx["user_service"] = services.UserService(uow)
    ctx["calendar_service"] = services.CalendarService(uow)
    ctx["subscription_service"] = services.SubscriptionService(uow)


async def after_job_end(ctx):
    if ctx.get("session"):
        await ctx["session"].close()


async def shutdown(ctx):
    if ctx.get("session"):
        await ctx["session"].close()
    await ctx["bot"].session.close()
    await ctx["engine"].dispose()


class WorkerSettings:
    functions = [
        notify_users,
        notify_user,
        enque_calendar_tasks,
        notify_expiring_subscription,
        notify_expired_subscription,
    ]
    on_startup = startup
    on_shutdown = shutdown
    on_job_start = on_job_start
    after_job_end = after_job_end
    timezone = pytz.timezone("Europe/Moscow")
    allow_abort_jobs = True
    redis_settings = config.redis.pool_settings
    cron_jobs = [
        cron(enque_calendar_tasks, hour=0, minute=0, max_tries=3, run_at_startup=True),
        cron(
            notify_expiring_subscription,
            minute=0,
        ),
        cron(
            notify_expired_subscription,
            minute=0,
        ),
    ]
